package com.gxa.ssm340.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

import java.util.Arrays;

/**
 * 设计一个切面
 * @author Lenovo
 */
//@Aspect
//@Component
public class LogAspect {

    /**
     * 声明切点
     * 要定义切点的完整路径信息:全部的包名+类名+方法（访问权限）
     *
     * 第一个*表示访问权限
     * 第二个表示类
     * 第三个* 表示方法
     * .. 表示任意类型的任意数量的参数
     */
    @Pointcut("execution(* com.gxa.ssm340.service.impl.*.*(..))")
    public void pointCut(){}

    //设计通知

    /**
     * 前置通知 通过@Before 实现
     *
     */
    @Before("pointCut()")
    public  void  before(JoinPoint joinPoint){

        String name = joinPoint.getSignature().getName();
        System.out.println("前置通知执行了... 方法名是："+name);
    }

    /**
     * 后置通知 通过@After 实现
     */
    @After("pointCut()")
    public  void  after(){
        System.out.println("后置通知执行了..");
    }

    /**
     * 后置抛出通知，出现异常的统一处理方法
     */
    @AfterThrowing(value = "pointCut()",throwing = "e")
    public  void  afterThrowing(Exception e){
        System.out.println("e:"+e);

        //获取异常的原因
        System.out.println("message:"+e.getMessage());
        System.out.println("后置抛出通知执行了...");
    }

    /**
     * 后置返回通知：本来没有异常的时候，正常返回时的处理方法
     */
    @AfterReturning("pointCut()")
    public void afterReturning(){
        System.out.println("后置返回通知执行了...");
    }

    /**
     * 环绕通知
     * 在执行时，需要通过执行连接点获取原方法
     */
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint){
        Object proceed = null;
//        Date date = new Date();
//        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSSS");
//        String time = simpleDateFormat.format(date);
//        String name = proceedingJoinPoint.getSignature().getName();
        Object[] args = proceedingJoinPoint.getArgs();
        try {
            System.out.println("前置通知2...  ");
//            System.out.println("方法名称："+name);
            if(args != null && args.length > 0){
                String s = Arrays.toString(args);
                System.out.println("参数为："+s);
            }else {
                System.out.println("该方法没有参数");
            }
//            System.out.println("方法调用时间："+time);
            proceed = proceedingJoinPoint.proceed();

            System.out.println("后置返回通知2... ");
//            System.out.println("返回值为："+proceed);

            return proceed;
        } catch (Throwable t) {
            System.out.println("异常发生了");
            System.out.println("后置抛出通知2...");
//            System.out.println("异常类型："+t.getClass());
//            System.out.println("异常信息："+t.getMessage());
            t.printStackTrace();

            StackTraceElement[] stackTrace = t.getStackTrace();
            for (StackTraceElement stackTraceElement : stackTrace) {
                //记录到日志文件
//                log.error(StackTraceElement);
            }
        }finally {
            System.out.println("后置通知2...");
//            System.out.println("方法结束调用时间："+time);
        }

        return proceed;
    }
}
